#include <windows.h>

/*CMATIX - Originally a standalone class, now part of RoboFo (SDIE)
CMATIX, or ColorMatrix is a library for searching a screen or select area of the screen for a matrix or array of pixels.
Written by Bradley Galloway
Copyright Notice: CMATIX (c) Bradley Galloway - 2012 */

/*Error Notice
May throw error when being debugged, due to not following Microsoft's standards.*/

#pragma once
#include <Windows.h>
typedef struct{
		long x;
		long y;
} TPOINT;

typedef long tpixel;

extern "C"{
	__declspec(dllexport) tpixel *ToPixelArray(int members, ...){
			__asm{
					mov eax, members
					shl eax, 2
					push eax
					call malloc
					add esp, 4
					cmp eax, 0
					jne _passerror
					mov eax, 0
					jmp jret
	_passerror:
					mov edi, eax
					mov ecx, members
					lea esi, [ebp+0xC]
	loopx:
					mov edx, [esi]
					mov [edi], edx
					add edi, 4
					add esi, 4
					dec ecx
					jnz loopx
	jret:
			}
	}
	__declspec(dllexport) bool TestMatrix(tpixel *pPixelMatrix, unsigned long ulWidth, unsigned long ulHeight,unsigned long ulX, unsigned long ulY, RGBQUAD *pPixelData, RECT *prctSearchArea){
		for(unsigned long ulMatrixX = 0; ulMatrixX<ulWidth;ulMatrixX++)
			for(unsigned long ulMatrixY = 0; ulMatrixY<ulHeight; ulMatrixY++)
				if(((*(tpixel*)(&pPixelData[((prctSearchArea->bottom-ulY-1)*prctSearchArea->right)+ulX]))&0x00FFFFFF)!=pPixelMatrix[(ulWidth*ulMatrixY)+ulMatrixX])return false;
		return true;
	}
	__declspec(dllexport) tpixel *GetScreenPixelData(RECT *prctArea){
		tpixel *pPixelData = new tpixel[(prctArea->right - prctArea->left) * (prctArea->bottom -prctArea->top)];
		BITMAPINFO BMPINFO = {0};
		BMPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
		BMPINFO.bmiHeader.biWidth = (prctArea->right - prctArea->left);
		BMPINFO.bmiHeader.biHeight = (prctArea->bottom - prctArea->top);
		BMPINFO.bmiHeader.biPlanes = 1;
		BMPINFO.bmiHeader.biBitCount = 32;
		BMPINFO.bmiHeader.biCompression = BI_RGB;
		HWND desktophwnd = GetDesktopWindow();
		HDC hdcSource = GetDC(desktophwnd);
		HDC hdcDestination = CreateCompatibleDC(hdcSource);
		HBITMAP hBMP = CreateCompatibleBitmap(hdcSource, (prctArea->right - prctArea->left),(prctArea->bottom - prctArea->top));
		SelectObject(hdcDestination,hBMP);
		BitBlt(hdcDestination,0,0,(prctArea->right - prctArea->left),(prctArea->bottom - prctArea->top), hdcSource,0,0,SRCCOPY); // depending on winapi version, add '| 0x40000000', usually for newer versions.
		GetDIBits(hdcDestination, hBMP, 0, (prctArea->bottom - prctArea->top), pPixelData, &BMPINFO, DIB_RGB_COLORS);
	//        ReleaseDC(desktophwnd, hdcSource);
		DeleteDC(hdcDestination);
		DeleteObject(hBMP);
			//delete[] (void*)&BMPINFO;
		return pPixelData;
	}
	__declspec(dllexport) tpixel *GetWindowPixelData(HWND hWindow, RECT *prctArea, bool brelease = false){
			tpixel *pPixelData = new tpixel[(prctArea->right - prctArea->left) * (prctArea->bottom -prctArea->top)];
			BITMAPINFO BMPINFO = {0};
			BMPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
			BMPINFO.bmiHeader.biWidth = (prctArea->right - prctArea->left);
			BMPINFO.bmiHeader.biHeight = (prctArea->bottom - prctArea->top);
			BMPINFO.bmiHeader.biPlanes = 1;
			BMPINFO.bmiHeader.biBitCount = 32;
			BMPINFO.bmiHeader.biCompression = BI_RGB;
			HDC hdcSource = GetDC(hWindow);
			HDC hdcDestination = CreateCompatibleDC(hdcSource);
			HBITMAP hBMP = CreateCompatibleBitmap(hdcSource, (prctArea->right - prctArea->left),(prctArea->bottom - prctArea->top));
			SelectObject(hdcDestination,hBMP);
		BitBlt(hdcDestination,0,0,(prctArea->right - prctArea->left),(prctArea->bottom - prctArea->top), hdcSource,0,0,SRCCOPY); // depending on winapi version, add '| 0x40000000', usually for newer versions.
			GetDIBits(hdcDestination, hBMP, 0, (prctArea->bottom - prctArea->top), pPixelData, &BMPINFO, DIB_RGB_COLORS);
			if(brelease) ReleaseDC(hWindow, hdcSource);
			DeleteDC(hdcDestination);
			DeleteObject(hBMP);
			//delete[] (void*)&BMPINFO;
			return pPixelData;
	}

	__declspec(dllexport) TPOINT ConstructPoint(unsigned long x, unsigned long y){
		TPOINT ptRet = {x, y};
		return ptRet;
	}

	__declspec(dllexport) TPOINT LocateMatrix(tpixel *pPixelMatrix, unsigned long ulWidth, unsigned long ulHeight, RECT *prctSearchArea, RGBQUAD *pPixelData){
	if(!(ulWidth%2 || ulHeight%2)) return ConstructPoint(-1, -1);
		for(unsigned long ulX = prctSearchArea->left + ((ulWidth-1)/2);ulX< (prctSearchArea->right -((ulWidth-1)/2));ulX++)
			for(unsigned long ulY = prctSearchArea->top + ((ulHeight-1)/2); ulY<(prctSearchArea->bottom - ((ulHeight-1)/2));ulY++){
				if(TestMatrix(pPixelMatrix, ulWidth, ulHeight, ulX, ulY, pPixelData, prctSearchArea))return ConstructPoint(ulX+((ulWidth-1)/2), ulY+((ulHeight-1)/2));
		}
	}
}

BOOL __stdcall DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved){
	return TRUE;
}